package ysq.xyg.controller;


import com.github.pagehelper.StringUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import ysq.xyg.model.info.ReturnEntity;
import ysq.xyg.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author yu sheng qiang
 * @create 2017-03-27 11:20
 **/
@Controller
@RequestMapping(value = "/file")
public class FileController {
    private static Logger log= LoggerFactory.getLogger(FileController.class);

    /**
     * 图片文件上传
     */
    @ResponseBody
    @RequestMapping(value = "/picture",method = RequestMethod.POST)
    public ReturnEntity photoUpload(MultipartFile file, HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IllegalStateException, IOException{
        ReturnEntity returnEntity=new ReturnEntity(BaseConstant.CODE_ERROR,"上传失败");
        if (file!=null) {// 判断上传的文件是否为空
            String path=null;// 文件路径
            String type=null;// 文件类型
            String fileName=file.getOriginalFilename();// 文件原名称
            System.out.println("上传的文件原名称:"+fileName);
            // 判断文件类型
            type=fileName.indexOf(".")!=-1?fileName.substring(fileName.lastIndexOf(".")+1, fileName.length()):null;
            if (type!=null) {// 判断文件类型是否为空
                if ("GIF".equals(type.toUpperCase())||"PNG".equals(type.toUpperCase())||"JPG".equals(type.toUpperCase())) {
                    // 项目在容器中实际发布运行的根路径
                    String realPath=request.getSession().getServletContext().getRealPath("/");
                    // 自定义的文件名称
                    String  trueFileName = DateUtil.DateToStr(new Date(),DateUtil.DATE_TIME_PATTERN_1)+ BaseUtil.acceptRandom(BaseUtil.NUMBER_CONTENT,6)+fileName;

                    //如果文件夹不存在则创建
                    File dicFile =new File(realPath+ProProperties.getInstance().getPictureURL());
                    if  (!dicFile .exists()  && !dicFile .isDirectory()){
                        dicFile .mkdir();
                    }

                    // 设置存放图片文件的路径
                    String realPictureUrl=ProProperties.getInstance().getPictureURL()+"/"+trueFileName;
                    path=realPath+realPictureUrl;
                    System.out.println("存放图片文件的路径:"+path);
                    // 转存文件到指定的路径
                    file.transferTo(new File(path));
                    System.out.println("文件成功上传到指定目录下");
                    returnEntity=new ReturnEntity(BaseConstant.CODE_SUCCESS,realPictureUrl,"");
                }else {
                    System.out.println("不是我们想要的文件类型,请按要求重新上传");
                    return null;
                }
            }else {
                System.out.println("文件类型为空");
                return null;
            }

        }else {
            System.out.println("没有找到相对应的文件");
            return null;
        }
        return returnEntity;
    }
    /**
     * 这里这里用的是MultipartFile[] myfiles参数,所以前台就要用<input type="file" name="myfiles"/>
     * 上传文件完毕后返回给前台[0`filepath],0表示上传成功(后跟上传后的文件路径),1表示失败(后跟失败描述)
     */
    @RequestMapping(value="/musicUpload")
    public String musicUpload(@RequestParam MultipartFile[] myfiles, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String realPath = request.getSession().getServletContext().getRealPath(ProProperties.getInstance().getPictureURL());//这里实现文件上传操作用的是commons.io.FileUtils类,它会自动判断路径是否存在,不存在会自动创建
        response.setContentType("text/plain; charset=UTF-8"); //设置响应给前台内容的数据格式
        PrintWriter out = response.getWriter();//设置响应给前台内容的PrintWriter对象
        //上传文件的原名(即上传前的文件名字)
        String newFileName = null;

        //如果只是上传一个文件,则只需要MultipartFile类型接收文件即可,而且无需显式指定@RequestParam注解
        //如果想上传多个文件,那么这里就要用MultipartFile[]类型来接收文件,并且要指定@RequestParam注解
        //上传多个文件时,前台表单中的所有<input type="file"/>的name都应该是myfiles,否则参数里的myfiles无法获取到所有上传的文件
        for(MultipartFile myfile : myfiles){
            if(myfile.isEmpty()){
                log.info("请选择文件后上传");
                out.print("请选择文件后上传");
                out.flush();
                return null;
            }else{
                String fileName=myfile.getOriginalFilename();// 文件原名称
                // 判断文件类型
                String type=fileName.indexOf(".")!=-1?fileName.substring(fileName.lastIndexOf(".")+1, fileName.length()):null;
                if(StringUtil.isNotEmpty(type)&&("mp3".equalsIgnoreCase(type)||"mp4".equalsIgnoreCase(type)||"ogg".equalsIgnoreCase(type)||"mov".equalsIgnoreCase(type))){
                }else{
                    type="mp3";
                }
                newFileName = DateUtil.DateToStr(new Date(),DateUtil.DATE_TIME_PATTERN_1)+ BaseUtil.acceptRandom(BaseUtil.NUMBER_CONTENT,6)+"."+type;
                log.info("文件名: " + newFileName+";文件原名: " + myfile.getOriginalFilename()+";文件名称: " + myfile.getName()+";文件长度: " + myfile.getSize()+";文件类型: " + myfile.getContentType());
                try {
                    //这里不必处理IO流关闭的问题,因为FileUtils.copyInputStreamToFile()方法内部会自动把用到的IO流关掉
                    //此处也可以使用Spring提供的MultipartFile.transferTo(File dest)方法实现文件的上传
                    FileUtils.copyInputStreamToFile(myfile.getInputStream(), new File(realPath, newFileName));
                } catch (IOException e) {
                    log.info("文件[" + newFileName + "]上传失败,堆栈轨迹如下");
                    e.printStackTrace();
                    out.print("文件上传失败，请重试！！");
                    out.flush();
                    return null;
                }
            }

        }
        //此时在Windows下输出的是[D:\Develop\apache-tomcat-6.0.36\webapps\AjaxFileUpload\\upload\愤怒的小鸟.jpg]
        //System.out.println(realPath + "\\" + originalFilename);
        //此时在Windows下输出的是[/AjaxFileUpload/upload/愤怒的小鸟.jpg]
        //System.out.println(request.getContextPath() + "/upload/" + originalFilename);
        //不推荐返回[realPath + "\\" + originalFilename]的值
        //因为在Windows下<img src="file:///D:/aa.jpg">能被firefox显示,而<img src="D:/aa.jpg">firefox是不认的
        out.print("0`" + request.getContextPath() + "/upload/" + newFileName);
        out.flush();
        return null;
    }
    /**
     * 这里这里用的是MultipartFile[] myfiles参数,所以前台就要用<input type="file" name="myfiles"/>
     * 上传文件完毕后返回给前台[0`filepath],0表示上传成功(后跟上传后的文件路径),1表示失败(后跟失败描述)
     */
    @RequestMapping(value="/fileUpload")
    public String addUser(@RequestParam MultipartFile[] myfiles, HttpServletRequest request, HttpServletResponse response ) throws IOException {
        String realPath = request.getSession().getServletContext().getRealPath(ProProperties.getInstance().getPictureURL());//这里实现文件上传操作用的是commons.io.FileUtils类,它会自动判断路径是否存在,不存在会自动创建
        response.setContentType("text/plain; charset=UTF-8"); //设置响应给前台内容的数据格式
        PrintWriter out = response.getWriter();//设置响应给前台内容的PrintWriter对象
        //上传文件的原名(即上传前的文件名字)
        String newFileName = null;
        //如果只是上传一个文件,则只需要MultipartFile类型接收文件即可,而且无需显式指定@RequestParam注解
        //如果想上传多个文件,那么这里就要用MultipartFile[]类型来接收文件,并且要指定@RequestParam注解
        //上传多个文件时,前台表单中的所有<input type="file"/>的name都应该是myfiles,否则参数里的myfiles无法获取到所有上传的文件
        for(MultipartFile myfile : myfiles){
            if(myfile.isEmpty()){
                log.info("请选择文件后上传");
                out.print("请选择文件后上传");
                out.flush();
                return null;
            }else{
                newFileName = DateUtil.DateToStr(new Date(),DateUtil.DATE_TIME_PATTERN_1)+ BaseUtil.acceptRandom(BaseUtil.NUMBER_CONTENT,6)+"."+BaseUtil.acceptFileType(myfile.getOriginalFilename());
                log.info("文件名: " + newFileName+";文件原名: " + myfile.getOriginalFilename()+";文件名称: " + myfile.getName()+";文件长度: " + myfile.getSize()+";文件类型: " + myfile.getContentType());
                try {
                    //这里不必处理IO流关闭的问题,因为FileUtils.copyInputStreamToFile()方法内部会自动把用到的IO流关掉
                    //此处也可以使用Spring提供的MultipartFile.transferTo(File dest)方法实现文件的上传
                    FileUtils.copyInputStreamToFile(myfile.getInputStream(), new File(realPath, newFileName));
                } catch (IOException e) {
                    log.info("文件[" + newFileName + "]上传失败,堆栈轨迹如下");
                    e.printStackTrace();
                    out.print("文件上传失败，请重试！！");
                    out.flush();
                    return null;
                }
            }
        }
        //此时在Windows下输出的是[D:\Develop\apache-tomcat-6.0.36\webapps\AjaxFileUpload\\upload\愤怒的小鸟.jpg]
        //System.out.println(realPath + "\\" + originalFilename);
        //此时在Windows下输出的是[/AjaxFileUpload/upload/愤怒的小鸟.jpg]
        //System.out.println(request.getContextPath() + "/upload/" + originalFilename);
        //不推荐返回[realPath + "\\" + originalFilename]的值
        //因为在Windows下<img src="file:///D:/aa.jpg">能被firefox显示,而<img src="D:/aa.jpg">firefox是不认的
        out.print("0`" + request.getContextPath() + "/upload/" + newFileName);
        out.flush();
        return null;
    }

    @ResponseBody
    @RequestMapping(value="/fileUploadEditor")
    public R fileUploadEditor(@RequestParam MultipartFile[] myfiles, HttpServletRequest request, HttpServletResponse response ) throws IOException {
        String realPath = request.getSession().getServletContext().getRealPath(ProProperties.getInstance().getPictureURL());//这里实现文件上传操作用的是commons.io.FileUtils类,它会自动判断路径是否存在,不存在会自动创建
        String newFileName = null;
        List<String> urlList = new ArrayList<String>();
        for(MultipartFile myfile : myfiles){
            if(myfile.isEmpty()){
                log.info("请选择文件后上传");
                return null;
            }else{
                newFileName = DateUtil.DateToStr(new Date(),DateUtil.DATE_TIME_PATTERN_1)+ BaseUtil.acceptRandom(BaseUtil.NUMBER_CONTENT,6)+"."+BaseUtil.acceptFileType(myfile.getOriginalFilename());
                log.info("文件名: " + newFileName+";文件原名: " + myfile.getOriginalFilename()+";文件名称: " + myfile.getName()+";文件长度: " + myfile.getSize()+";文件类型: " + myfile.getContentType());
                try {
                    FileUtils.copyInputStreamToFile(myfile.getInputStream(), new File(realPath, newFileName));
                    urlList.add(request.getContextPath() + "/upload/" + newFileName);
                } catch (IOException e) {
                    log.info("文件[" + newFileName + "]上传失败,堆栈轨迹如下");
                    e.printStackTrace();
                    return null;
                }
            }
        }
        return R.ok().put("errno", 0).put("data", urlList);
    }

    /**
     * 压缩，保存时按配置文件加入查看下载
     * @param isDelete Y:删除，N：保留
     * @param kind 0:按原图大小生成新图，1：按指定的大小生成新图，2：按原图宽高比例生成新图-按指定的宽度，3：按原图宽高比例生成新图-按指定的高度 4：按原图宽高比例生成新图-按指定的宽和高中较大的尺寸，5：按原图宽高比例生成新图-按指定的宽和高中较小的尺寸
     * @param width 压缩宽 当kind=1生效
     * @param height 压缩高 当kind=1生效
     */
    @RequestMapping(value="/fileUploadCompress")
    public String uplodCompress(@RequestParam MultipartFile[] myfiles, HttpServletRequest request, HttpServletResponse response,@RequestParam(defaultValue = "N") String isDelete,@RequestParam(defaultValue ="0") int kind,@RequestParam(defaultValue ="360") int width,@RequestParam(defaultValue ="120") int height) throws IOException {
        String realPath = request.getSession().getServletContext().getRealPath(ProProperties.getInstance().getPictureURL());//这里实现文件上传操作用的是commons.io.FileUtils类,它会自动判断路径是否存在,不存在会自动创建
        response.setContentType("text/plain; charset=UTF-8"); //设置响应给前台内容的数据格式
        PrintWriter out = response.getWriter();//设置响应给前台内容的PrintWriter对象
        String newFileName = null;
        String sizeFileName = null;
        for(MultipartFile myfile : myfiles){
            if(myfile.isEmpty()){
                log.info("请选择文件后上传");
                out.print("请选择文件后上传");
                out.flush();
                return null;
            }else{
                newFileName=getFilePath(realPath,myfile.getOriginalFilename());
                log.info("文件名: " + newFileName+";文件原名: " + myfile.getOriginalFilename()+";文件名称: " + myfile.getName()+";文件长度: " + myfile.getSize()+";文件类型: " + myfile.getContentType());
                try {
                    File targetFile = new File(realPath,newFileName);
                    FileUtils.copyInputStreamToFile(myfile.getInputStream(), targetFile);
                    //压缩后上传并删除原文件
                    //此时targetFile应该就是file流
                    sizeFileName = ImangeUtil.createNewImage(targetFile, kind, width, height);
                    if("Y".equalsIgnoreCase(isDelete)) {
                        //删除源文件
                        targetFile.delete();
                    }
                } catch (Exception e) {
                    log.info("文件[" + newFileName + "]上传失败,堆栈轨迹如下");
                    e.printStackTrace();
                    out.print("文件上传失败，请重试！！");
                    out.flush();
                    return null;
                }
            }
        }
        String comFileName=newFileName.substring(0, newFileName.lastIndexOf("."))+ "_NEW"
                + newFileName.substring(newFileName.lastIndexOf("."), newFileName.length());
        out.print("0`" + ProProperties.getInstance().getPictureURL()+comFileName);
        out.flush();
        return null;
    }

    private String getFilePath(String realPath,String sourceFileName) {
        Date nowDate = new Date();
        String catalog=File.separator + DateUtil.DateToStr(new Date(),DateUtil.DATE_YEAR)
                + File.separator +DateUtil.DateToStr(new Date(),DateUtil.DATE_MONTH) + File.separator
                + DateUtil.DateToStr(new Date(),DateUtil.DATE_DAY);
        // yyyy/MM/dd
        String fileFolder = realPath + catalog;
        File file = new File(fileFolder);
        if (!file.isDirectory()) {
            // 如果目录不存在，则创建目录
            file.mkdirs();
        }
        // 生成新的文件名
        String fileName = DateUtil.DateToStr(new Date(),DateUtil.DATE_TIME_PATTERN_2)
                + RandomUtils.nextInt(100, 9999) + "." + StringUtils.substringAfterLast(sourceFileName, ".");
        return catalog + File.separator + fileName;
    }
}
